# All content Copyright 2010 Cyrus Omar <cyrus.omar@gmail.com> unless otherwise
# specified.
#
# Contributors:
#     Cyrus Omar <cyrus.omar@gmail.com>
#
# This file is part of, and licensed under the terms of, the atomic-hedgehog
# package.
#
# The atomic-hedgehog package is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The atomic-hedgehog package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with the atomic-hedgehog package. If not, see <http://www.gnu.org/licenses/>.

from operator import iadd  # += doesn't work when the lval is an expression

from ahh.sim import ModelNode, param, state


class Current(ModelNode):
	def __init__(self, parent, basename="Current"):
		ModelNode.__init__(self, parent, basename)

	@param
	def current():
		"""Current magnitude."""

	def _pre_finalize(self):
		self.parent.I += self.current

class GenericSynapse(Current):
	"""Abstract base class for synapses.

	A synapse is an additive current of the form g*(reversal-v), where g is
	typically a	state variable, reversal is a parameter, v is a state variable
	defined in parent.v and currents is a parameter defined in model.currents.
	"""
	def __init__(self, parent, basename="Synapse"):
		Current.__init__(self, parent, basename)

	@param
	def current(default="g*(reversal - v)"):
		"""Synaptic current."""

	@param
	def reversal():
		"""Reversal potential."""

class ExpSynapse(Synapse):
	"""Exponential synapse."""
	def __init__(self, parent, basename="ExpSynapse"):
		Synapse.__init__(self, parent, basename)

	@param
	def tau():
		"""Synaptic integration time constant."""

	@param
	def lookup(default="allocation[idx_state]"):
		"""The expression to use to lookup the state variable's value."""

	@param
	def input_conductance(default=0.0):
		"""Additional input conductance (e.g. from incoming spikes)."""

	@state
	def g(reader="const cl_type name = lookup;",
	      independent_updater="g - DT/tau*g"):
		"""Synaptic conductance."""

class AlphaSynapse(Synapse):
	"""Alpha synapse."""
	def __init__(self, model, basename="AlphaSynapse"):
		Synapse.__init__(self, model, basename)

class DoESynapse(Synapse):
	"""Difference of exponentials synapse."""
	def __init__(self, model, basename="DoESynapse"):
		Synapse.__init__(self, model, basename)
